package com.gitee.cirnochat.file.service.storage.impl;


import com.gitee.cirnochat.common.config.CosClientConfig;
import com.gitee.cirnochat.common.exception.BusinessException;
import com.gitee.cirnochat.common.model.enums.ErrorCode;
import com.gitee.cirnochat.file.service.storage.CosService;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.model.*;
import com.qcloud.cos.transfer.TransferManager;
import com.qcloud.cos.transfer.TransferManagerConfiguration;
import com.qcloud.cos.transfer.Upload;
import com.qcloud.cos.utils.IOUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

@RequiredArgsConstructor
@Service
@Slf4j
public class CosServiceImpl implements CosService {
    private final CosClientConfig cosClientConfig;
    private final COSClient cosClient;

    //region 实现的接口方法

    @Override
    public void uploadFile(String uploadPath, File file) {
        this.putObject(uploadPath, file);
    }

    @Override
    public void uploadFile(String uploadPath, String localFilePath) {
        this.putObject(uploadPath, localFilePath);
    }

    @Override
    public PutObjectResult uploadFileToCos(String uploadPath, File file) {
        return this.putObject(uploadPath, file);
    }

    @Override
    public void deleteFile(String filePath) {
        this.deleteObject(filePath);
    }

    //endregion

    //region cos 对象储存方法

    /**
     * 上传对象
     *
     * @param key           唯一键
     * @param localFilePath 本地文件路径
     * @return {@link PutObjectResult}
     */
    @Override
    public PutObjectResult putObject(String key, String localFilePath) {
        PutObjectRequest putObjectRequest = new PutObjectRequest(cosClientConfig.getBucket(), key,
                new File(localFilePath));
        return cosClient.putObject(putObjectRequest);
    }

    /**
     * 上传对象
     *
     * @param key  唯一键
     * @param file 文件
     * @return {@link PutObjectResult}
     */
    @Override
    public PutObjectResult putObject(String key, File file) {
        PutObjectRequest putObjectRequest = new PutObjectRequest(cosClientConfig.getBucket(), key,
                file);
        return cosClient.putObject(putObjectRequest);
    }

    @Override
    public Upload putPartObject(String key, File file) {
        UploadPartRequest uploadPartRequest = new UploadPartRequest();
        TransferManager transferManager = new TransferManager(cosClient);
        // 分块上传阈值和分块大小分别设置为 5MB 和 1MB（若不特殊设置，分块上传阈值和分块大小的默认值均为5MB）
        TransferManagerConfiguration transferManagerConfiguration = new TransferManagerConfiguration();
        transferManagerConfiguration.setMultipartUploadThreshold(5 * 1024 * 1024);
        transferManagerConfiguration.setMinimumUploadPartSize(1 * 1024 * 1024);
        transferManager.setConfiguration(transferManagerConfiguration);
        return transferManager.upload(cosClientConfig.getBucket(), key, file);
    }

    /**
     * 获取对象
     *
     * @param key
     * @param outputStream
     */
    @Override
    public void getObject(String key, OutputStream outputStream) {
        GetObjectRequest getObjectRequest = new GetObjectRequest(cosClientConfig.getBucket(), key);
        InputStream cosObjectInput;
        try {
            COSObject cosObject = cosClient.getObject(getObjectRequest);
            cosObjectInput = cosObject.getObjectContent();
            IOUtils.copy(cosObjectInput, outputStream);
            cosObjectInput.close();
        } catch (IOException e) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, e.getMessage());
        }
    }

    /**
     * 删除对象
     * @param key
     */
    @Override
    public void deleteObject(String key) {
        DeleteObjectRequest deleteObjectRequest = new DeleteObjectRequest(cosClientConfig.getBucket(), key);
        try {
            cosClient.deleteObject(deleteObjectRequest);
        } catch (CosServiceException e) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, e.getMessage());
        }
    }

    //endregion
}
